﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.Utils.Menu;
using System.ComponentModel.Design;
using ProgNetComponents.Validation.Rules;
using ProgNetComponents.Validation;

namespace ProgNetComponentsDx.Validation.Design
{
    public partial class ValidationRulesEditor : XtraForm
    {
        private ValidationRulesEditor()
        {
            InitializeComponent();
        }

        private DataTable Dt;
        private DataSet Ds;

        Dictionary<ValidationRuleForTable, ValidationRuleForTable> rulesMap = new Dictionary<ValidationRuleForTable, ValidationRuleForTable>();

        public ValidationRulesEditor(IDesignerHost host, ValidationRulesForTableCollection rules, DataSet ds, DataTable dt)
        {
            InitializeComponent();
            propertyGrid1.Site = host.RootComponent.Site;
            propertyGrid1.RunMethod("SetFlag", (ushort)2, true);
            propertyGrid1.PropertyTabs.AddTabType(typeof(System.Windows.Forms.Design.EventsTab));
            propertyGrid1.RunMethod("ShowEventsButton", true);
            this.host = host;
            Rules = new ValidationRulesForTableCollection();
            orgRules = rules;

            CreateMenuItems();
            InitSettings();
            Dt = dt;
            Ds = ds;

            lbTables.DataSource = Rules;
            //if (dt != null)
            //    lbTables.Items.Add(dt);
            //else if (ds != null)
            //{
            //    foreach(DataTable d in ds.Tables)
            //        lbTables.Items.Add(d);
            //}
           
        }
        
        private ValidationRulesForTableCollection orgRules;

        private ValidationRulesForTableCollection Rules
        {
            get;
            set;
        }

        private IDesignerHost host;
        private ValidationRuleCollection CurrentRules
        {
            get { return lbRules.DataSource as ValidationRuleCollection; }
        }
        private ValidationRuleForTable CurrentRule
        {
            get { return lbTables.SelectedItem as ValidationRuleForTable; }
        }

        List<ValidationRule> deletedRules = new List<ValidationRule>();

        private DXPopupMenu popupMenu = new DXPopupMenu();
        private DXMenuItem lastItem = null;

        private void CreateMenuItems()
        {
            var rules = ProgNetComponents.Validation.ValidationRuleHelper.GetRules(host);
            List<DXMenuItem> list = new List<DXMenuItem>();
            foreach (var kvp in rules)
            {
                DXMenuItem i = new DXMenuItem(kvp.Key, new EventHandler(this.popupMenu_Click));
                i.Tag = kvp.Value;
                list.Add(i);
            }
            list.Sort((x, y) =>
            {
                return x.Caption.CompareTo(y.Caption);
            });
            foreach (var i in list)
                popupMenu.Items.Add(i);

            this.btnAdd.DropDownControl = popupMenu;
        }
        private void InitSettings()
        {
            foreach (var s in orgRules)
            {
                ValidationRuleForTable t = new ValidationRuleForTable(s.Table, s.Filter, null);
                rulesMap.Add(t, s);
                t.Rules.AddRange(s.Rules);
                Rules.Add(t);
            }
        }

        void popupMenu_Click(object sender, EventArgs e)
        {
            lastItem = sender as DXMenuItem;
            if (lastItem != null)
                btnAdd.Text = "Add " + lastItem.Caption;
            else
                btnAdd.Text = "Add";

            AddItem();
        }

        private void lbTables_SelectedValueChanged(object sender, EventArgs e)
        {
            if (CurrentRule != null)
            {
                lbRules.DataSource = CurrentRule.Rules;
                meFilter.Text = CurrentRule.Filter;
                meFilter.Enabled = true;
            }
            else
            {
                lbRules.DataSource = null;
                meFilter.Text = null;
                meFilter.Enabled = false;
            }
            lbRules.Refresh();
        }

        private void lbRules_SelectedValueChanged(object sender, EventArgs e)
        {
            this.propertyGrid1.SelectedObject = lbRules.SelectedItem;
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            AddItem();
        }
        
        private void AddItem()
        {
            if (lastItem != null)
            {
                if (CurrentRules != null)
                {
                    var rule = ProgNetComponents.Validation.ValidationRuleHelper.Create(lastItem.Caption, host);
                    if (rule != null)
                    {
                        CurrentRules.Add(rule);
                        lbRules.SelectedItem = rule;
                    }
                }
            }
            else
            {
                btnAdd.ShowDropDown();
            }
        }

        public void MergeResults()
        {
            foreach (var rule in deletedRules)
            {
                try
                {
                    rule.Dispose();
                    host.DestroyComponent(rule);
                }
                catch { }
            }
            orgRules.Clear();
            foreach (var r in Rules)
                orgRules.Add(r);
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            ValidationRule rule = lbRules.SelectedItem as ValidationRule;
            if (rule != null)
            {
                if (CurrentRules != null)
                {
                    CurrentRules.Remove(rule);
                    deletedRules.Add(rule);
                    lbRules.Refresh();
                }
            }
        }
        
        private void btnClear_Click(object sender, EventArgs e)
        {
            if (CurrentRules != null)
            {
                var rules = CurrentRules.ToArray();
                foreach (var rule in rules)
                {
                    CurrentRules.Remove(rule);
                    deletedRules.Add(rule);
                }
                lbRules.Refresh();
            }
        }

        private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            lbRules.Refresh();
        }

        private void btnClearAll_Click(object sender, EventArgs e)
        {
            foreach (var rt in Rules)
            {
                var rules = rt.Rules.ToArray();
                foreach (var rule in rules)
                {
                    rt.Rules.Remove(rule);
                    deletedRules.Add(rule);
                }
            }
            Rules.Clear();

            lbRules.Refresh();
        }

        private void btnAddRuleForTable_Click(object sender, EventArgs e)
        {
            DataTable dt = null;
            if (Dt != null)
                dt = Dt;
            else if (Ds != null)
            {
                List<DataTable> tables = new List<DataTable>();
                foreach (DataTable t in Ds.Tables)
                    tables.Add(t);

                object res = ProgNetComponentsDx.Forms.SelectForm.SelectDialog("New Validation Rule for Table", "Select Table", tables.ToArray());
                if (res != null && res is DataTable)
                    dt = (DataTable)res;
            }
            if (dt != null)
            {
                ValidationRuleForTable r = new ValidationRuleForTable(dt);
                Rules.Add(r);
                lbTables.SelectedValue = r;
            }
        }

        private void btnRemoveRuleForTable_Click(object sender, EventArgs e)
        {
            if (CurrentRule != null)
            {
                int idx = lbTables.SelectedIndex;
                deletedRules.AddRange(CurrentRule.Rules);
                
                if(rulesMap.ContainsKey(CurrentRule))
                    rulesMap.Remove(CurrentRule);

                Rules.Remove(CurrentRule);
                
                lbTables.SelectedIndex = -1;
                if (Rules.Count > idx)
                {
                    lbTables.SelectedIndex = idx;
                }
                else
                {
                    lbTables.SelectedIndex = Rules.Count - 1;
                }

            }
        }

        private void meFilter_EditValueChanged(object sender, EventArgs e)
        {
            if (CurrentRule != null)
            {
                CurrentRule.Filter = meFilter.Text;
            }
        }

        private void propertyGrid1_SelectedObjectsChanged(object sender, EventArgs e)
        {
            propertyGrid1.Site = null;
            if (propertyGrid1.SelectedObject != null)
            {
                if (propertyGrid1.SelectedObject is ValidationRule)
                {
                    propertyGrid1.Site = ((ValidationRule)propertyGrid1.SelectedObject).Site;
                    propertyGrid1.PropertyTabs.AddTabType(typeof(System.Windows.Forms.Design.EventsTab));
                    propertyGrid1.RunMethod("ShowEventsButton", true);
                }
            }
        }

    }
}
